package model;

import java.io.Serializable;

import model.i.IState;
import model.playingfield.PlayingField;


/**
 * @author christopher
 * This is the State. It represents the state of the game at any
 * point in time, and records, specifically:
 *
 * Regarding the players:
 * 		what players are currently playing the game
 * 		where their pieces are
 * 		whose turn it is to make a move
 *
 * Regarding the game:
 * 		If the game is still running
 * 		what settings are in effect
 * 		 	Is music enabled?
 * 			Are sound effects enabled?
 */
public class State implements IState, Serializable {

    /**
     *
     */
    private static final long serialVersionUID = 1L;

    /**
     *  Players currently playing. Null indicates that the player is no longer in game.
     */
    private Player[] players;

    /**
     * A representation of the playingfield
     */
    private PlayingField playingfield;

    /**
     * Statistics for the game in progress
     */
    private Statistics statistics;

    /**
     * The following are state variables, used in order to determine what phase
     * of a players turn the Model currently is in, and data related to it:
     *   - playerSelected : a player is currently selected
     *   - dieRolled      : the die has been rolled
     *   - spotSelected   : a piece has been selected
     *   - moveMade 	  : the move has been made
     *   - gameInProgress : whether or not the game is currently in progress
     *
     *   - currentPlayer  : the Player which the current turn belongs to
     *   - currentDieValue : the result of the current players die throw
     */
    private boolean playerSelected  = false;
    private boolean dieRolled	    = false;
    private boolean spotSelected    = false;
    private boolean moveMade 	    = false;
    private boolean gameInProgress  = false;
    private Integer currentPlayer   = 0;
    private int	    currentDieValue = 0;

    /**
     * The constructor simply initiates the core data structures, which are passed down
     * from upstread. All state variables will be set to their standard null (or equivalent)
     * values by default.
     * @param players
     * @param playingfield
     * @param statistics
     */
    public State(Player[] players, PlayingField playingfield, Statistics statistics) {
        this.players = players;
        this.playingfield = playingfield;
        this.statistics = statistics;
    }

    public State() {
    }

    /**
     * remove a player from the game, for example, in the event
     * that he or she is booted from the game for some reason.
     */
    @Override
    public void removePlayer(Player player) {
        /**
         * First is to remove the Player from the
         * HashMap.
         *
         * Then it should go to playerfield, and remove the
         * the players pieces, change their locations to null.
         *
         */

        //Remove the player
        for(int i = 0; i < players.length - 1; i++){
            if(players[i] == player){
                players[i] = null;
            }
        }

        //Remove all pieces corresponding to that player at the field
            for(int k=0; k < playingfield.getPieceLocations().length - 1; k++){
                Integer[][] list = playingfield.getPieceLocations();
                if(list[player.getID()][k] != null){
                    list[player.getID()][k] = null;
                }
            }
    }


    /*
     * The following are various getters and setters
     */

    /**
     * @return a specific player
     */
    public Player getPlayer(int player) {
        return players[player];
    }

    /**
     * For testing propose
     * Checks if there is players into the game
     * @param players
     * @return
     */
    public boolean hasPlayers(Player[] players){
        boolean hasPlayers = false;
        for(int i=0; i < players.length; i++){
            if(players[i] != null){
                hasPlayers = true;
                return hasPlayers;
            }
        }
        return hasPlayers;
    }

    /**
     * @param players the players to set
     */
    public void setPlayers(Player[] players) {
        this.players = players;
    }


    /**
     * @return the dieRolled
     */
    @Override
    public boolean isDieRolled() {
        return dieRolled;
    }

    /**
     * @param dieRolled the dieRolled to set
     */
    @Override
    public void setDieRolled(boolean dieRolled) {
        this.dieRolled = dieRolled;
    }

    /**
     * @return the spotSelected
     */
    @Override
    public boolean hasMoved() {
        return spotSelected;
    }

    /**
     * @param spotSelected the spotSelected to set
     */
    @Override
    public void setSpotSelected(boolean spotSelected) {
        this.spotSelected = spotSelected;
    }

    /**
     * @return the currentDieValue
     */
    public int getCurrentDieValue() {
        return currentDieValue;
    }

    /**
     * @param currentDieValue the currentDieValue to set
     */
    public void setCurrentDieValue(int currentDieValue) {
        this.currentDieValue = currentDieValue;
    }

    /**
     * @return the moveMade
     */
    @Override
    public boolean isMoveMade() {
        return moveMade;
    }

    /**
     * @param moveMade the moveMade to set
     */
    @Override
    public void setMoveMade(boolean moveMade) {
        this.moveMade = moveMade;
    }

    /**
     * @return the currentPlayer
     */
    @Override
    public Integer getCurrentPlayer() {
        return currentPlayer;
    }

    /**
     * @param currentPlayer the currentPlayer to set
     */
    @Override
    public void setCurrentPlayer(Integer currentPlayer) {
        this.currentPlayer = currentPlayer;
        System.out.println("STATE: currentplaye is " + this.currentPlayer);
    }

    /**
     * Return locations of player pieces.
     */
    @Override
    public Integer[][] getPlayerLocations() {
        return playingfield.getPieceLocations();
    }


    /**
     * @param playerSelected the playerSelected to set
     */
    public void setPlayerSelected(boolean playerSelected) {
        this.playerSelected = playerSelected;
    }

    /**
     * @return the playerSelected
     */
    public boolean isPlayerSelected() {
        return playerSelected;
    }

    /**
     * @return the gameInProgress
     */
    public boolean isGameInProgress() {
        return gameInProgress;
    }

    /**
     * @param gameInProgress the gameInProgress to set
     */
    public void setGameInProgress(boolean gameInProgress) {
        this.gameInProgress = gameInProgress;
    }

    @Override
    public void resetStateVars() {

        playerSelected = false;
        dieRolled = 	 false;
        spotSelected = 	 false;
        moveMade = 		 false;

        currentPlayer =  null;
        currentDieValue = 0;
    }

    @Override
    public PlayingField getPlayingField() {

        return playingfield;
    }

    @Override
    public Statistics[] getStatistics() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public int getNumOfPlayers() {
        // TODO Auto-generated method stub
        return players.length;
    }

    Battle battle; //Should probably not be in State
    @Override
    public void setBattle(Battle b) {
            battle = b;
    }

    @Override
    public Battle getBattle() {
        return battle;
    }
}
